package yxy.banana.socket;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

import com.google.protobuf.ByteString;
import com.google.protobuf.MessageLite;

import yxy.apple.protobuf.Constants;
import yxy.apple.protobuf.Message;
import yxy.apple.protobuf.Message.Parcal;
import yxy.apple.util.Sequencer;

public class ParcalUtility {

	private static final Sequencer sequencer = new Sequencer(0, Integer.MAX_VALUE);

	public static Parcal build(String tag, long source, long destination, int proto, MessageLite content) throws Exception {
		return ParcalUtility.build(tag, source, destination, proto, content.toByteString());
	}

	public static Parcal build(String tag, long source, long destination, int proto, ByteString content) throws Exception {
		try {
			Parcal.Builder builder = Parcal.newBuilder();
			builder.setVersion(Constants.Version);
			builder.setSequence(sequencer.next());
			builder.setTimestamp(System.currentTimeMillis());
			if (tag != null) {
				builder.setTag(tag);
			}
			if (source != 0) {
				builder.setSource(source);
			}
			if (destination != 0) {
				builder.setDestination(destination);
			}
			builder.setProto(proto);
			builder.setData(content);
			Parcal message = builder.build();
			return message;
		} catch (Exception e) {
			throw e;
		}
	}

	public static String toString(Parcal parcal) {
		return ParcalUtility.toString(parcal.getSequence(), parcal.getTag(), parcal.getTimestamp(), parcal.getSource(), parcal.getDestination(),
				parcal.getProto(), parcal.getData());
	}

	public static String toString(int sequence, String tag, long timestamp, long source, long destination, int proto, ByteString data) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("{");
		buffer.append("\r\n\ttime: ");
		buffer.append(new DateTime(timestamp).toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")));
		buffer.append("\r\n\tsequence: ");
		buffer.append(sequence);
		buffer.append("\r\n\ttag: ");
		buffer.append(tag);
		buffer.append("\r\n\tsource: ");
		buffer.append(NetworkElement.assemble(source));
		buffer.append("\r\n\tdestination: ");
		buffer.append(NetworkElement.assemble(destination));
		buffer.append("\r\n\tproto: ");
		buffer.append(proto);
		buffer.append("\r\n\tdata: ");
		buffer.append(data.toStringUtf8());
		buffer.append("\r\n}");
		return buffer.toString();
	}

	public static boolean controlling(Parcal parcal) {
		int proto = parcal.getProto();
		return controlling(proto);
	}

	public static boolean controlling(int proto) {
		return (proto & 0x00FFFFFF) == proto;
	}

}
